package com.zwps.common.tool.ffmpeg;

import java.util.List;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class FfmpegParseVideoTool {
//    private static final Pattern FORMAT_PATTERN = Pattern.compile("^\\s*([D ])([E ])\\s+([\\w,]+)\\s+.+$");
//    private static final Pattern ENCODER_DECODER_PATTERN = Pattern.compile("^\\s*([D ])([E ])([AVS]).{3}\\s+(.+)$", 2);
//    private static final Pattern PROGRESS_INFO_PATTERN = Pattern.compile("\\s*(\\w+)\\s*=\\s*(\\S+)\\s*", 2);
    private static final Pattern SIZE_PATTERN = Pattern.compile("(\\d+)x(\\d+)", 2);
    private static final Pattern FRAME_RATE_PATTERN = Pattern.compile("([\\d.]+)\\s+(?:fps|tb\\(r\\))", 2);
    private static final Pattern BIT_RATE_PATTERN = Pattern.compile("(\\d+)\\s+kb/s", 2);
    private static final Pattern SAMPLING_RATE_PATTERN = Pattern.compile("(\\d+)\\s+Hz", 2);
    private static final Pattern CHANNELS_PATTERN = Pattern.compile("(mono|stereo)", 2);
//    private static final Pattern SUCCESS_PATTERN = Pattern
//            .compile("^\\s*video\\:\\S+\\s+audio\\:\\S+\\s+global headers\\:\\S+.*$", 2);
    private static final Pattern p1 = Pattern.compile("^\\s*Input #0, (\\w+).+$\\s*", 2);
    private static final Pattern p2 = Pattern.compile("^\\s*Duration: (\\d\\d):(\\d\\d):(\\d\\d)\\.(\\d).*$", 2);
    private static final Pattern p3 = Pattern.compile("^\\s*Stream #\\S+: ((?:Audio)|(?:Video)|(?:Data)): (.*)\\s*$",
            2);

    /**
     * 处理媒体信息流
     * 
     * @param list
     * @return
     */
    public static MultimediaInfo parseMultimediaInfo(List<String> list) {
        MultimediaInfo info = null;
        int step = 0;
        for (String line : list) {
            if (line == null) {
                break;
            }
            String type;
            String specs;
            if (step == 0) {
                Matcher m = p1.matcher(line);
                if (m.matches()) {
                    specs = m.group(1);
                    info = new MultimediaInfo();
                    info.setFormat(specs);
                    ++step;
                }
            } else {
                Matcher m;
                if (step == 1) {
                    m = p2.matcher(line);
                    if (m.matches()) {
                        long hours = Long.parseLong(m.group(1));
                        long minutes = Long.parseLong(m.group(2));
                        long seconds = Long.parseLong(m.group(3));
                        long dec = Long.parseLong(m.group(4));
                        long duration = dec * 100L + seconds * 1000L + minutes * 60L * 1000L
                                + hours * 60L * 60L * 1000L;
                        info.setDuration(duration);
                        ++step;
                    }
                } else if (step == 2) {
                    m = p3.matcher(line);
                    if (m.matches()) {
                        type = m.group(1);
                        specs = m.group(2);
                        StringTokenizer st;
                        String token;
                        Matcher m2;
                        int i;
                        boolean parsed;
                        int bitRate;
                        if ("Video".equalsIgnoreCase(type)) {
                            MultimediaInfo.VideoInfo video = new MultimediaInfo.VideoInfo();
                            st = new StringTokenizer(specs, ",");

                            for (i = 0; st.hasMoreTokens(); ++i) {
                                token = st.nextToken().trim();
                                if (i == 0) {
                                    video.setDecoder(token);
                                } else {
                                    parsed = false;
                                    m2 = SIZE_PATTERN.matcher(token);
                                    if (!parsed && m2.find()) {
                                        bitRate = Integer.parseInt(m2.group(1));
                                        int height = Integer.parseInt(m2.group(2));
                                        // video.setSize(new VideoSize(bitRate, height));
                                        video.setWidth(bitRate);
                                        video.setHeight(height);
                                        parsed = true;
                                    }

                                    m2 = FRAME_RATE_PATTERN.matcher(token);
                                    if (!parsed && m2.find()) {
                                        try {
                                            float frameRate = Float.parseFloat(m2.group(1));
                                            video.setFrameRate(frameRate);
                                        } catch (NumberFormatException var20) {
                                        }

                                        parsed = true;
                                    }

                                    m2 = BIT_RATE_PATTERN.matcher(token);
                                    if (!parsed && m2.find()) {
                                        bitRate = Integer.parseInt(m2.group(1));
                                        video.setBitRate(bitRate);
                                    }
                                }
                            }

                            info.setVideo(video);
                        } else if ("Audio".equalsIgnoreCase(type)) {
                            MultimediaInfo.AudioInfo audio = new MultimediaInfo.AudioInfo();
                            st = new StringTokenizer(specs, ",");

                            for (i = 0; st.hasMoreTokens(); ++i) {
                                token = st.nextToken().trim();
                                if (i == 0) {
                                    audio.setDecoder(token);
                                } else {
                                    parsed = false;
                                    m2 = SAMPLING_RATE_PATTERN.matcher(token);
                                    if (!parsed && m2.find()) {
                                        bitRate = Integer.parseInt(m2.group(1));
                                        audio.setSamplingRate(bitRate);
                                        parsed = true;
                                    }

                                    m2 = CHANNELS_PATTERN.matcher(token);
                                    if (!parsed && m2.find()) {
                                        String ms = m2.group(1);
                                        if ("mono".equalsIgnoreCase(ms)) {
                                            audio.setChannels(1);
                                        } else if ("stereo".equalsIgnoreCase(ms)) {
                                            audio.setChannels(2);
                                        }

                                        parsed = true;
                                    }

                                    m2 = BIT_RATE_PATTERN.matcher(token);
                                    if (!parsed && m2.find()) {
                                        bitRate = Integer.parseInt(m2.group(1));
                                        audio.setBitRate(bitRate);
                                    }
                                }
                            }
                            info.setAudio(audio);
                        }
                    }
                }
            }
        }

        if (info == null) {
            throw new RuntimeException("获取视频信息失败");
        } else {
            return info;
        }
    }
}